# coding=utf-8
__author__ = 'Michael'

import model
from print_nice import print_nice
import edit_model
import json
from compare_model import compare
from jsonschema import Draft4Validator

class Shell(object):


    def __init__(self):

        self.model_dict = {}
        self.sv = edit_model.edit()

    def start(self):

        while True:

            cmd = raw_input("AMS $> ")
            self.parsecommand(cmd)

    def parsecommand(self, cmd):
        if (cmd==""):
            return
        if cmd[:4].lower() == "help":
            self.printhelp()
        if cmd[:4].lower() == "exit":
            self.exit()
        if cmd[:4].lower() == "read":
            c = cmd.split()
            if len(c) < 2:
                print "Error: please provide filename"
                return
            tmpmod=model.Model()
            try:
                tmpmod.feed(c[1])
            except Exception:
                print "Errors while loading model %s. Please check model file integrity" % c[1]
                return


            if (tmpmod is not None) and (tmpmod.name not in self.model_dict):
                self.model_dict[tmpmod.name]=tmpmod
                print "Model %s loaded sucessfully" % tmpmod.name
            else:
                print "Error while loading model %s" % c[1]



        c = cmd.split()

#abstract model
        if c[0] == "model.abstract": # need to validate the input command
            if len(c) < 3:
                print "Error: please provide model name and abstraction level"
                return
            c[2] = int(c[2])
            if (c[1] not in self.model_dict):
                print "Error: No such model"
                return
            tmpmod=self.model_dict[c[1]]
            tmpmod.abstract(c[2], tmpmod.maindict, tmpmod.abstract_dict)
            print_nice(tmpmod.abstract_dict)

#flatten model
        if c[0] == "model.flatten": # need to validate the input command
            if len(c) < 2:
                print "Please provide model name"
                return
            if c[1] not in self.model_dict:
                print "Error: no such model"
                return

            tmpmod=self.model_dict[c[1]]
            print_nice(tmpmod.flatten(tmpmod.maindict))

#list loaded models
        if c[0] == "model.list":
            for model_name in self.model_dict:
                print model_name

#compare to model
        if c[0] == "model.compare":
            if len(c)<3:
                print "Please provide model names to compare"
                return
            print "comparison"
            if c[1] not in self.model_dict:
                print "The model '%s' is not loaded, Please load '%s'" % (c[1], c[1])
                return
            if c[2] not in self.model_dict:
                print "The model '%s' is not loaded, Please load '%s'" % (c[2], c[2])
                return

            d = compare(self.model_dict[c[1]].maindict, self.model_dict[c[2]].maindict)
            d.print_diff()

#save model
        if c[0] == "save": # need to validate the input command
            if len(c) < 3:
                print "Error: Please provide model name and file name to save in"
                return
            else:
                if (c[1] not in self.model_dict):
                    print "Error. No such model"
                    return
                tmpmod=self.model_dict[c[1]]
                with open(c[2], "w") as outfile:

                    json.dump(tmpmod.maindict, outfile)
                print "Model %s saved succesfully to file %s" % (c[1], c[2])


        if c[0] == "model.print":
            if (len(c)<2):
                print "Error: Please provide the model name"
                return
            else:
                if (c[1] not in self.model_dict):
                    print "Error: No such model"
                    return
                tmpmod=self.model_dict[c[1]]
                print_nice(tmpmod.maindict)

        if c[0]=="model.remove":
            if len(c)<3:
                print "Please provide model name and object to remove"
                return
            modname=c[1]
            if (modname not in self.model_dict):
                print "Error: no such model"
                return
            tmpmod=self.model_dict[modname]
            objname=c[2]
            if (objname not in tmpmod.maindict[u'objects']):
                print "Error: Model does not contain object " + objname
                return
            del tmpmod.maindict[u'objects'][objname]
            print "Object " + objname + " removed successfully"

        if c[0]=="model.add":
            if len(c)<4:
                print "Please provide model name, object name and path to definition"
                return
            modname=c[1]
            if(modname not in self.model_dict):
                print "Error: No such model"
                return
            objname=c[2]
            objpath=c[3]

            loadobj=json.loads(open(objpath).read())
            sch=json.loads(open("object.schema").read())
            v=Draft4Validator(sch)
            errors = sorted(v.iter_errors(loadobj), key=lambda e: e.path)
            for error in errors:
                print "ERROR IN JSON FILE  :  %s -----> :%s" % (list(error.path), error.message)
            if errors:
                print "Errors occured. Please check the model definition integrity. Total number of errors: %s" % str(len(errors))
                return

            self.model_dict[modname].maindict[u'objects'][objname]=loadobj

            print "Object %s was added to model %s successfully" % (objname, modname)


        if c[0]=="model.update":
            if len(c)<4:
                print "Please provide model name, target object name and path to the new definition"
                return
            modname=c[1]
            if modname not in self.model_dict:
                print "Error: no such model"
                return
            objname=c[2]
            if (objname not in self.model_dict[modname].maindict[u'objects']):
                print "Error: Model %s does not contain object %s" % (modname, objname)
                return
            defpath=c[3]
            loadobj=json.loads(open(defpath).read())
            sch=json.loads(open("object.schema").read())
            v=Draft4Validator(sch)
            errors = sorted(v.iter_errors(loadobj), key=lambda e: e.path)
            for error in errors:
                print "ERROR IN JSON FILE  :  %s -----> :%s" % (list(error.path), error.message)
            if errors:
                print "Object definition contains errors. Please verify object definition. Total errors: " + str(len(errors))
                return

            self.model_dict[modname].maindict[u'objects'][objname]=loadobj
            print "Object %s updated sucessfully" % objname







    def printhelp(self):
        print("Possible commands: \n help \n exit "
              "\n model.list "
              "\n model.read [path] "
              "\n model.abstract [modelname] [abstraction_level] "
              "\n model.flatten [modelname]"
              "\n model.compare [name1] [name2]"
              "\n model.print [modelname]"
              "\n model.add [modelname] [objectname_to_add] [path_to_definition] "
              "\n model.remove [modelname] [objectname_to_remove] "
              "\n model.update [modelname] [objectname_to_update] [path_to_definition]")

    def exit(self):
        print "Good Bye!"
        exit()
        pass
        #here we will clean temporaries





def main():
    sh = Shell()
    sh.start()


if __name__ == "__main__":
    main()